День 2 Летней школы Julia 2025
В Julia, как и во многих других языках программирования, исключения используются для обработки ошибок и неожиданных ситуаций, которые могут возникнуть во время выполнения программы. Основные конструкции для работы с исключениями в Julia — это try, throw и catch.
Основные конструкции:
-
try— блок кода, в котором может возникнуть исключение. Если исключение возникает, выполнение кода в блоке try прерывается, и управление передается в блок catch. -
throw— используется для явного выброса исключения. Вы можете выбросить как встроенные исключения, так и пользовательские. -
catch— блок, который обрабатывает исключение, выброшенное в блоке try. В блоке catch можно указать переменную, которая будет содержать информацию об исключении.
10 / 0 # / деление даёт Float-значение, вспомним про Inf
Но если мы целочисленно поделим 10 на ноль, то вызовется исключение
DivideError.
10 ÷ 0
DomainError Возникает тогда, когда аргумент не входит в область определения нашей функции.
Обратите внимание, что в этой ошибке указывается, какое значение принял аргумент.
sqrt(-1)
BoundsError возникает тогда, когда мы выходим за границы массива.
И здесь также указывается, какое значение аргумента привело к ошибке.
a = [1,2,3]
a[4]
MethodError возникает тогда, когда функция есть, а подходящего метода с аргументами таких типов нет. И заметьте, что проблема не в функции max, а в функции сравнения, находящейся внутри функции max.
max(1,"123")
Если переменная не определена, то возникает UndefVarError и указывается имя неопределённой функции.
abs(u)
Функция something возвращает первый аргумент, не являющийся nothing.
something(nothing, nothing, 45)
ArgumentError возникает тогда, когда метод есть, но по самой логике программы должно произойти исключение.
Есть ли хоть что-то в ничего? Значит нужно выдать ошибку.
something(nothing)
Представим, что у нас есть программа, которая запускает веб-приложение и
отрисовывает функцию
a ÷ b * t
И у нас есть ползунок, который позволяет управлять их значениямию
По-хорошему, программимст должен был озаботиться значениями в ползунке.
И при b == 0 произойдёт ошибка, которая останавливает всю программу, останавливает сервер и пр. Просто из-за того, что в графическом интерфейсе кто-то указал деление на ноль.
a = 100 # @param {type:"slider", min:0, max:100, step:1}
b = 0 # @param {type:"slider", min:0, max:100, step:1}
using Plots
t = 0:10
plot(t, (a ÷ b) * t )
Чтобы решить эту проблему, используют конструкцию
try catch
Если между try и catch происходит throw, то catch ловит это исключение и обрабатывает.
(В нашем случае мы выводим "Произошла ошибка")
using Plots
a = 100 # @param {type:"slider", min:0, max:100, step:1}
b = 1 # @param {type:"slider", min:0, max:100, step:1}
try
t = 0:10
plot(t, (a ÷ b) * t ) # (в a ÷ b происходит throw)
catch e
println("Произошла ошибка: ", e)
return nothing
end
Если мы хотим создать свой собственный тип исключений, то нужно унаследоваться от абстрактного типа Exception.
Внутри check_value происходит throw.
А сам check_value вызывается между try и catch.
То есть логика работы с исключениями
trythrowcatch
struct MyCustomException <: Exception
msg::String
end
function check_value(x::Integer)
if x < 0
throw(MyCustomException("Значение x = $x не может быть отрицательным"))
else
println("Значение корректно: ", x)
end
end
try
check_value(-1)
catch e
if e isa MyCustomException
println("Поймано пользовательское исключение: ", e.msg)
else
println("Поймано другое исключение: ", e)
end
end